package cn.yx.common.core.util.bean;

import cn.yx.common.core.constant.message.bean.BeanUtilMessageKey;
import cn.yx.common.core.exception.CommonException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>Bean相关工具类，如bean的拷贝，依赖于spring-beans</p>
 *
 * @author Wgssmart
 */
@Slf4j
public final class BeanUtil {

    private BeanUtil() {
    }

    /**
     * 把源对象拷贝到目标对象
     *
     * @param source 源对象
     * @param target 目标对象
     * @param <E>    源对象泛型
     * @param <T>    目标对象泛型
     * @return
     */
    public static <E, T> T copy(E source, T target) {
        BeanUtils.copyProperties(source, target);
        return target;
    }

    /**
     * 把源对象拷贝到目标对象，目标对象需要有无参构造方法
     *
     * @param source      源对象
     * @param targetClass 目标对象类
     * @param <E>         源对象泛型
     * @param <T>         目标对象泛型
     * @return
     */
    public static <E, T> T copy(E source, Class<T> targetClass) {
        try {
            T t = targetClass.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(source, t);
            return t;
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                 InvocationTargetException e) {
            log.error("Bean copy error, src: {}, target: {}, error: {}", source.getClass(), targetClass, e.getMessage());
            // @SimplifiedChinese=对象拷贝异常
            // @English=Bean copy error
            throw new CommonException(BeanUtilMessageKey.BEAN_COPY_ERROR, e);
        }
    }

    /**
     * 把列表中指定的源对象拷贝到另外一个列表中的目标对象，注意：这不是一个简单的List的拷贝，而是List内部对象的重新拷贝
     *
     * @param source      源对象列表
     * @param targetClass 目标对象类
     * @param <E>         源对象泛型
     * @param <T>         目标对象泛型
     * @return
     */
    public static <E, T> List<T> copy(List<E> source, Class<T> targetClass) {
        List<T> targetList = new ArrayList<>();
        for (E e : source) {
            targetList.add(copy(e, targetClass));
        }
        return targetList;
    }

}
